package inner

/**
 * Created by Administrator on 2019/09/28.
 */
data class BU(val v1 : String , val v2 : Int){

    operator fun unaryMinus() = BU(v1.reversed(),  -v2)

    operator fun plus(a : BU) =  BU(this.v1 + a.v1, this.v2 + a.v2)
}


fun rbu() : BU
{
    return BU("hello", 1)
}

fun main(args: Array<String>) {
    val (v1, _) = rbu()
    println(v1)

    val num = mapOf("one" to 1, "two" to 2)
    num.mapValues { (_, value) -> {"${value}!"} }
    println(num)

    val obj = 1

    val b1 = BU("123", 32);
    val b2 = BU("456", 12);
    println(-b1)
    println(b1 + b2)

    var a:String = "123"
    var b:String? = null
    println(b?.length ?: 0)

    var strs : List<String?> = listOf("hello", "world", null)
    for (item in strs){
        item?.let {
            println(item)
        }
    }

    fun length(s: String) = s.length
    val oddLength = compose(::isOdd, ::length)
    val strings = listOf("a", "ab", "abc")

    println(strings.filter(oddLength))

    Person("xm", 23, "").let {
        println(it)
        it.moveTo("newyork")
        it.increment()
        println(it)
    }

    val num2 = mutableListOf("one", "two", "three", "four")
    num2.map { it.length }.filter { it > 3 }.let(::println)

    val str1:String? = "Hello"
    str1?.let {
        println("let() call on $str1")
        it.length
    }

    var mfi = num2.first().let {
        fi ->
        println(fi)
        if(fi.length > 5) fi else "!" + fi + "!"
    }.toUpperCase()
    println(mfi)

    with(num2){
        println("with id called on $this")
    }

    val hexNumberRegex = run {
        val digits = "0-9"
        val hexDigits = "A-Fa-f"
        val sign = "+-"

        Regex("[$sign]?[$digits$hexDigits]+")
    }

    for (match in hexNumberRegex.findAll("+1234 -FFFF not-a-number")) {
        println(match.value)
    }
}

fun isOdd(x: Int) = x % 2 != 0

fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
    return { y -> f(g(y)) }
}

class A{
    inner class B{
        fun Int.foo(){
            val a = this@A
            val b = this@B

            val c = this
            val c1 = this@foo

            val funLit = lambda@ fun String.(){
                val d = this
            }
        }
    }
}

data class Person(var name : String, var age : Int, var addr : String){

    fun moveTo(addr : String){
        this@Person.addr = addr
    }

    fun increment(){
        age++
    }
}